<!--
 * @Author: cjx
 * @Date: 2023-05-12 08:38:58
 * @LastEditTime: 2023-05-12 11:15:23
 * @Description: 对话框组件
 * @param {Boolen} value 控制对话框显隐
 * @param {Boolen} footerHide 底部按钮显隐
-->
<template>
  <Modal
    class="cd-modal"
    ref="cdModal"
    v-model="computedModelValue"
    :title="props.title"
    :closable="props.closable"
    :mask-closable="props.maskClosable"
    :width="width"
    :footer-hide="props.footerHide"
    :loading="props.loading"
    :scrollable="props.scrollable"
    :fullscreen="props.fullscreen"
    :draggable="props.draggable"
    :ok-text="props.okText"
    :cancel-text="props.cancelText"
    :styles="computedStyle"
    :class-name="className"
    @on-ok="onOk"
    @on-cancel="onCancel"
    @on-visible-change="onVisibleChange"
  >
    <template #header>
      <div class="ivu-modal-header-inner" style="position: relative">
        <slot name="header">{{ props.title }}</slot>
      </div>
    </template>

    <!-- 主内容 -->
    <div
      class="cd-modal-content"
      ref="cusContentRef"
      :style="`${minHeightStr};${maxHeightStr};overflow-y: auto;overflow-x: hidden;`"
    >
      <slot></slot>
    </div>

    <!-- 底部按钮插槽 -->
    <template #footer>
      <div class="cd-modal-btns" v-if="!props.footerHide">
        <slot name="footer">
          <Button class="cd-modal-btns-item" type="primary" :loading="loading" @click="onOk">确认</Button>
          <Button class="cd-modal-btns-item" @click="onCancel">取消</Button>
        </slot>
      </div>
    </template>
  </Modal>
</template>

<script setup lang="ts">
import { computed, onMounted, ref, useAttrs } from 'vue'
defineOptions({ name: 'CdModal' })
const props = defineProps({
  modelValue: {
    type: Boolean,
    default: false
  },
  title: {
    type: String,
    default: ''
  },
  closable: {
    type: Boolean,
    default: true
  },
  maskClosable: {
    type: Boolean,
    default: false
  },
  size: {
    type: String,
    default: 'normal',
    validator: (val: string) => ['small', 'normal', 'large'].includes(val)
  },
  footerHide: {
    type: Boolean,
    default: false
  },
  loading: {
    type: Boolean,
    default: false
  },
  scrollable: {
    type: Boolean,
    default: false
  },
  fullscreen: {
    type: Boolean,
    default: false
  },
  draggable: {
    type: Boolean,
    default: false
  },
  okText: {
    type: String,
    default: '确定'
  },
  cancelText: {
    type: String,
    default: '取消'
  },
  styles: {
    type: Object,
    default: () => ({
      top: '50px'
    })
  },
  className: {
    type: String,
    default: ''
  },
  minHeight: {
    type: String,
    default: '250'
  },
  maxHeight: {
    type: String,
    default: ''
  }
})

const computedModelValue = computed({
  get: () => props.modelValue,
  set: () => emits('update:modelValue')
})

const attrs = useAttrs()
const emits = defineEmits(['update:modelValue', 'on-visible-change', 'on-ok', 'on-cancel'])
const width = computed(() => {
  const SIZE_OBJ = {
    normal: '800',
    small: '520',
    large: '1200'
  }
  // 如果存在自定义宽度，则取自定义值
  return attrs.width || SIZE_OBJ[props.size as keyof typeof SIZE_OBJ]
})

const minHeightStr = computed(() => `min-height:${props.minHeight}px`)
const maxHeightStr = computed(() => (props.maxHeight ? `maxheight:${props.maxHeight}px` : ''))
const computedStyle = computed(() => ({ top: '50px', ...props.styles }))

// 可在此方法中，对窗口弹出时进行数据初始化
const onVisibleChange = (visible: boolean) => {
  if (visible) {
    emits('on-visible-change')
  }
}
const onOk = () => {
  emits('on-ok', () => {
    emits('update:modelValue', false)
  })
}
const onCancel = () => {
  emits('update:modelValue', false)
  emits('on-cancel')
}

// 是否设置最大高达
const cusContentRef = ref()
const initOnMaxheight = () => {
  // 展示全屏时不设置
  if (!props.fullscreen && !props.maxHeight) {
    const docHeight = document.body.offsetHeight
    let maxHeight = ''
    if (docHeight < 550) {
      maxHeight = '250px'
    } else if (docHeight >= 550 && docHeight < 650) {
      maxHeight = '400px'
    } else {
      maxHeight = '650px'
    }

    const $content = cusContentRef.value
    $content.style['maxHeight'] = maxHeight
  }
}

onMounted(() => {
  initOnMaxheight()
})
</script>

<style lang="less" scoped>
.vertical .cd-modal-content {
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.cd-modal-btns {
  text-align: center;
  &-item {
    padding-left: 20px;
    padding-right: 20px;
  }
}
.cd-modal-header-extra {
  position: absolute;
  right: 30px;
  display: inline-block;
}
</style>
